#include "mainobject.h"

void MainObject::installTranslator(){
    QSettings settings;
    QTranslator *translator = new QTranslator(this);
    QString dir = QApplication::applicationDirPath();
#ifdef Q_OS_MAC
    dir = QApplication::applicationDirPath()+"/../Resources/";
#endif
//    QMessageBox::information(0, "ENTrap", "dir = "+dir);
    if(translator->load(settings.value(EN_LOCALE, 0).toInt()==0?
                               "entrap_en":
                               "entrap_ru", dir)){
        QApplication::installTranslator(translator);
    }else{
        qDebug() << "Can't find translator";
    }
}

void MainObject::run(QApplication *app){
    QCoreApplication::setApplicationName(EN_APP_NAME);
    QCoreApplication::setOrganizationName(EN_ORG_NAME);
    QSettings settings;
    installTranslator();
    QStringList env = QProcess::systemEnvironment();
    QString defaultLoc = "";
    enFound = false;
    enLine = "";
    optionsWin = new OptionsWin();
    fieldWin = new TextFieldWin();
    hotkeyEditor = new HotKeyEditor();
    about = new About();
    qDebug() << QApplication::applicationDirPath() << QApplication::applicationFilePath() <<
            QApplication::applicationName();
    for(int i = 0; i<env.size(); i++){
        QString str = env[i];
//        qDebug() << "var = " << str;
        if(str.startsWith(EN_PROGRAMFILES)){
            defaultLoc = str.section("=", 1, 1) + EN_DEFAULT_FOLDER;
        }
    }
    QString loc = settings.value(EN_LOCATION, "").toString();
    qDebug() << "Program location: " << loc;
    bool showOptions = false;
#ifdef Q_OS_WIN32
    if(""==loc){
        settings.setValue(EN_LOCATION, defaultLoc);
        showOptions = true;
        loc = defaultLoc;
    }
    QFile file(loc + EN_EXECUTABLE);
    if(!file.exists()){
        showOptions = true;
    }else{
        enFound = true;
        enLine = loc + EN_EXECUTABLE;
    }
#endif
    connectHotkeys();
    qDebug() << "Show options" << showOptions;
    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(QIcon(":/icons/res/icon32.png"));
    trayMenu = new QMenu();
    //Setup tray menu
#ifdef Q_OS_MAC
    QAction *toggleAction = new QAction(tr("Show/hide window"), this->trayMenu);
    connect(toggleAction, SIGNAL(triggered()), this, SLOT(toggleTextField()));
    trayMenu->addAction(toggleAction);
#endif
    QAction *optionsAction = new QAction(tr("Options"), this->trayMenu);
    connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
    trayMenu->addAction(optionsAction);

    QAction *aboutAction = new QAction(tr("About"), this->trayMenu);
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
    trayMenu->addAction(aboutAction);

    qDebug() << "tr" << tr("Exit");
    QAction *exitAction = new QAction(tr("Exit"), this->trayMenu);
    connect(exitAction, SIGNAL(triggered()), this, SLOT(exitClicked()));
    trayMenu->addAction(exitAction);

#ifdef Q_OS_MAC
    QMenuBar *menuBar = new QMenuBar(0);
    QMenu *menu = new QMenu(menuBar);
    menuBar->addMenu(menu);

    optionsAction = new QAction("Options", this->trayMenu);
    connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
    menu->addAction(optionsAction);

    aboutAction = new QAction("About", this->trayMenu);
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(aboutClicked()));
    menu->addAction(aboutAction);

    exitAction = new QAction("Exit", this->trayMenu);
    connect(exitAction, SIGNAL(triggered()), this, SLOT(exitClicked()));
    menu->addAction(exitAction);

#endif
    //tray menu end

    trayIcon->setContextMenu(trayMenu);
    trayIcon->show();
    connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
            this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
    if(showOptions)
        optionsWin->show();
    else{
        if(settings.value(EN_TEXT_VISIBLE, QVariant(EN_TEXT_VISIBLE_DEF)).toBool())
            toggleTextField();
    }
}

MainObject* MainObject::instance_ = 0;

MainObject* MainObject::instance(){
        if (!instance_)
                instance_ = new MainObject();
        return instance_;
}

void MainObject::exitClicked(){
    trayIcon->hide();
    qApp->quit();
}

void MainObject::optionsClicked(){
    optionsWin->raise();
    optionsWin->show();
}

bool MainObject::callENMac(QStringList input, QString *output){
    QProcess process(this);
    process.start("osascript");
    process.waitForStarted();
    for(int i = 0; i<input.size(); i++){
        qDebug() << input[i];
        process.write(input[i].toUtf8()+"\r\n");
    }
    process.closeWriteChannel();
    process.waitForReadyRead(-1);
    if(process.exitCode()!=0){
        output->append(QString::fromUtf8(process.readAllStandardError(), -1).trimmed());
//        qDebug() << "Failed to call en mac: " << output << QSystemTrayIcon::supportsMessages();
        fieldWin->raise();
        QMessageBox::critical(0, tr("Evernote trap"),
                              tr("Can't communicate with Evernote, error was: ")+*output);
        return false;
    }
    output->append(QString::fromUtf8(process.readAllStandardOutput(), -1));
//    qDebug() << "after read all mac " << output <<
//            " return: " << process.exitCode() <<
//            process.exitStatus();
    process.waitForFinished(-1);
    return true;
}

bool MainObject::callEN(QString operation, QStringList params, QString input, QString *output){
    if(!enFound){
        return false;
    }
    QProcess process(this);
    params.insert(0, operation);
    qDebug() << "Calling " << enLine << ", params: " << params;
    process.start(enLine, params);
    process.waitForStarted();
    if(input != "")
        process.write(input.toLocal8Bit());
    process.waitForReadyRead(-1);
    if(process.exitCode()!=0){
        output->append(QString::fromUtf8(process.readAllStandardError(), -1).trimmed());
        qDebug() << "Failed to call en: " << output;
        trayIcon->showMessage(tr("Evernote trap"),
                              tr("Can't communicate with Evernote, error was: ")+*output,
                              QSystemTrayIcon::Critical, 1000);
        return false;
    }
    output->append(QString::fromUtf8(process.readAllStandardOutput(), -1));
//    qDebug() << "after read all " << output <<
//            " return: " << process.exitCode() <<
//            process.exitStatus();
    process.waitForFinished(-1);
    return true;
}

QString MainObject::maskAllShit(QString aString){
    aString.replace("\\", "\\\\");
    aString.replace("\"", "\\\"");
    return QString("\"")+aString+"\"";
}

bool MainObject::createFileNote(QString aFile, QString aNotebook, QString aType, QStringList tags){
QSettings settings;
QFile file(QDir::tempPath()+"/en"+QUuid::createUuid().toString()+(aType=="html"? ".html": ".txt"));
if(!file.open(QIODevice::WriteOnly))
    return false;
file.write(aFile.toLocal8Bit());
file.flush();
file.close();
#ifdef Q_OS_MAC
    QStringList input;
    QString tag = " tags {";
    for(int i = 0; i<tags.size(); i++){
        if(i>0)
            tag.append(",");
        tag.append(maskAllShit(tags[i]));
    }
    tag.append("}");
    input <<
            "tell application \"Evernote\"" <<
            "create note from file "+maskAllShit(aFile)+" "+
            " notebook "+maskAllShit(aNotebook)+
            (tags.size()>0? tag: "") <<
            "end tell";
    QString output;
    if(!callENMac(input, &output)){
        return false;
    }
    return true;
#endif
#ifdef Q_OS_WIN32
    QStringList params;
    params.append("/n");
    params.append(aNotebook);
    for(int i = 0; i<tags.size(); i++){
        params.append("/t");
        params.append(tags[i]);
    }
    if(settings.value(EN_PREMIUM, EN_PREMIUM_DEF).toBool()){
        params.append("/i");
        QFileInfo orig(aFile);
        params.append(orig.fileName());

        params.append("/s");
        params.append(file.fileName());

        params.append("/a");
    } else {
        params.append("/s");
    }
    params.append(aFile);
    QString output;
    if(!callEN("createNote", params, "", &output)){
        return false;
    }
    return true;
#endif
file.remove();
}

bool MainObject::createTextNote(QString aNote, QString aNotebook, QString aTitle, QString aType, QStringList tags){
    QFile file(QDir::tempPath()+"/en"+QUuid::createUuid().toString()+(aType=="html"? ".html": ".txt"));
    if(!file.open(QIODevice::WriteOnly))
        return false;
    file.write(aNote.toLocal8Bit());
    file.flush();
    file.close();
#ifdef Q_OS_MAC
    QStringList input;
    QString tag = " tags {";
    for(int i = 0; i<tags.size(); i++){
        if(i>0)
            tag.append(",");
        tag.append(maskAllShit(tags[i]));
    }
    tag.append("}");
    input <<
            "tell application \"Evernote\"" <<
            "create note from file "+maskAllShit(file.fileName())+" "+
            "title "+maskAllShit(aTitle)+" notebook "+maskAllShit(aNotebook)+
            (tags.size()>0? tag: "") <<
            "end tell";
    QString output;
    if(!

       Mac(input, &output)){
        file.remove();
        return false;
    }
#endif
#ifdef Q_OS_WIN32
    QStringList params;
    params.append("/n");
    params.append(aNotebook);
    params.append("/i");
    params.append(aTitle);
    for(int i = 0; i<tags.size(); i++){
        params.append("/t");
        params.append(tags[i]);
    }

    params.append("/s");
    params.append(file.fileName());
    QString output;
    if(!callEN("createNote", params, "", &output)){
        file.remove();
        return false;
    }
#endif
    file.remove();
    return true;
}

QStringList MainObject::getNotebooks(){
    QString parse;
#ifdef Q_OS_WIN32
    QStringList params;
    if(!callEN("listNotebooks", params, "", &parse)){
        QStringList empty;
        return empty;
    }
#endif
#ifdef Q_OS_MAC
    QStringList input;
    input <<
            "tell application \"Evernote\"" <<
            "set nbstr to \"\"" <<
            "set nbs to every notebook" <<
            "repeat with nb in nbs" <<
            "set nbstr to nbstr & name of nb & return & linefeed" <<
            "end repeat" <<
            "return nbstr" <<
            "end tell";
    if(!callENMac(input, &parse)){
        QStringList empty;
        return empty;
    }
#endif
    qDebug() << "Notebooks: " << parse;
    QStringList notebooks = parse.split("\r\n", QString::SkipEmptyParts);
    notebooks.sort();
    qDebug() << "Notebooks: " << notebooks;
    return notebooks;
}

void MainObject::connectHotkeys(){
    QSettings settings;
    QString hk = settings.value(EN_TEXT_HOTKEY, EN_TEXT_HOTKEY_DEF).toString();
    QKeySequence seq(hk);
    GlobalShortcutManager::instance()->connect(seq, this, SLOT(toggleTextField()));
}

void MainObject::disconnectHotkeys(){
    QSettings settings;
    QString hk = settings.value(EN_TEXT_HOTKEY, EN_TEXT_HOTKEY_DEF).toString();
    QKeySequence seq(hk);
    GlobalShortcutManager::instance()->disconnect(
            seq, this, SLOT(toggleTextField()));
}

void MainObject::toggleTextField(bool force){
    qDebug() << "show/hide text field";
    if(!fieldWin->isVisible()){
        fieldWin->show();
    }else{
        if(fieldWin->isActiveWindow() || force)
            fieldWin->hide();
        else{
            fieldWin->show();
        }
    }
}

void MainObject::trayActivated(QSystemTrayIcon::ActivationReason reason){
#ifdef Q_OS_WIN32
    if(reason==QSystemTrayIcon::Trigger){
        toggleTextField(true);
    }
#endif
}

void MainObject::aboutClicked(){
    about->show();
    about->raise();
    about->activateWindow();
}
